package com.sc.nft.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.sc.nft.dao.*;
import com.sc.nft.entity.*;
import com.sc.nft.entity.congestive.GiftCT;
import com.sc.nft.entity.dto.*;
import com.sc.nft.entity.vo.*;
import com.sc.nft.entity.vo.ecology.EcologyCastGasVO;
import com.sc.nft.entity.vo.secondEquityProp.EquityPropsLastConsignDetailsVO;
import com.sc.nft.entity.vo.secondEquityProp.RealAmountVO;
import com.sc.nft.enums.*;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.helper.MessageQueueHelper;
import com.sc.nft.service.*;
import com.sc.nft.sup.ErrorCode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 用户权益道具表服务接口实现
 *
 * @author Sun
 * @description 由 Mybatisplus Code Generator 创建
 * @since 2023-03-28 10:28:43
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class UserEquityPropsServiceImpl implements UserEquityPropsService {
    private final UserEquityPropsDao userEquityPropsDao;
    private final UserEquityPropsLogDao userEquityPropsLogDao;
    private final UserWalletService userWalletService;
    private final UserAssetsDao userAssetsDao;
    private final PropGiftDao propGiftDao;
    private final UserChainInfoDao userChainInfoDao;
    private final UserInfoDao userInfoDao;
    private final EquityPropsDao equityPropsDao;
    private final UserAssetsService userAssetsService;
    private final UserEcologyPointsService userEcologyPointsService;
    private final SecondEquityPropsConfigService secondEquityPropsConfigService;
    private final SecondEquityPropsConfigDao secondEquityPropsConfigDao;
    private final MessageQueueHelper messageQueueHelper;
    private final DigitalCollectionProductInfoDao digitalCollectionProductInfoDao;
    private final DigitalCollectionDao digitalCollectionDao;
    private final UserRelevanceService userRelevanceService;
    private final StaticDataDao staticDataDao;
    private final PropEquityVestInDao propEquityVestInDao;


    @Override
    public IPage<MallEquityUserHoldVo> pageEquityHold(MallEquityUserHoldDTO mallEquityUserHold) {
        return userEquityPropsDao.pageEquityHold(new Page<>(mallEquityUserHold.getPageNo(), mallEquityUserHold.getPageSize()), mallEquityUserHold.getPropId(), mallEquityUserHold.getUserId());
    }

    @Override
    public IPage<MallUserEquityPropsVO> pageUserEquityProps(VistInFlagUserDTO vistInFlagUserDTO) {
        PropEquityVestIn propEquityVestIn = propEquityVestInDao.getFlag(vistInFlagUserDTO.getFlag());
        if (propEquityVestIn == null) {
            throw new GlobalRunTimeException("无效的访问标识");
        }
        return userEquityPropsDao.pageUserEquityProps(vistInFlagUserDTO.getUserId(), propEquityVestIn.getId(),
                vistInFlagUserDTO.getStatus(), new Page<>(vistInFlagUserDTO.getPageNo(), vistInFlagUserDTO.getPageSize()));
    }

    @Override
    public Integer getHavingCountByUserId(Long equityPropsId, Long userId) {
        return userEquityPropsDao.getHavingCountByUserId(equityPropsId, userId);
    }

    @Override
    public Integer getHavingCountByUserId(Long equityPropsId, EquityPropsTypeEnum equityPropsType, Long userId) {
        return userEquityPropsDao.getHavingCountByUserId(equityPropsId, equityPropsType, userId);
    }

    @Override
    public List<UserEquityProps> getHavingListByUserIdAndEquityPropsIdAndLimit(Long userId, Long equityPropsId, Integer size) {
        return userEquityPropsDao.getHavingListByUserIdAndEquityPropsIdAndLimit(equityPropsId, userId, size);
    }


    @Override
    public Boolean updateBatchById(List<UserEquityProps> list) {
        list.forEach(userEquityProps -> userEquityProps.setHoldingStatus(UserEquityPropsHoldingStatusEnum.FREEZE));
        return userEquityPropsDao.updateBatchById(list);
    }

    /**
     * 修改用户权益道具状态
     *
     * @param ids
     * @param statusEnum
     */
    @Override
    public Boolean updateHoldStatusBatchById(List<Long> ids, UserEquityPropsHoldingStatusEnum statusEnum, UserEquityPropsHoldingStatusEnum beforeStatusEnum) {
        return userEquityPropsDao.updateHoldStatusBatchById(ids, statusEnum, beforeStatusEnum);
    }

    @Override
    public Boolean freezePropsToUseByIds(String ids, Long userId, Integer count, String relationTitle, Long relationId) {
        //查询出所有的权益道具
        List<UserEquityProps> userEquityPropsList = userEquityPropsDao.getListByUserIdAndIds(userId, ids, UserEquityPropsHoldingStatusEnum.FREEZE);
        if (userEquityPropsList.size() > 0) {
            String userEquityPropsIds = userEquityPropsList.stream().map(UserEquityProps::getId).map(String::valueOf).collect(Collectors.joining(","));
            //插入日志
            UserEquityPropsLog userEquityPropsLog = new UserEquityPropsLog();
            userEquityPropsLog.setUserId(userId);
            userEquityPropsLog.setUserEquityPropsId(userEquityPropsIds);
            userEquityPropsLog.setFirstTitle(userEquityPropsList.get(0).getFirstTitle());
//            userEquityPropsLog.setPropsId(userEquityPropsList.get(0).getEquityPropsId());
            userEquityPropsLog.setCreationContent(userEquityPropsList.get(0).getCreationContent());
            userEquityPropsLog.setGetType(null);
            userEquityPropsLog.setUseType(UserEquityPropsUseTypeEnum.FIRST_BUY);
            userEquityPropsLog.setTypeClassify(userEquityPropsList.get(0).getTypeClassify());
            userEquityPropsLog.setIsConsume(Boolean.TRUE);
            userEquityPropsLog.setCount(count);
            userEquityPropsLog.setRelationTitle(relationTitle);
            userEquityPropsLog.setRelationId(relationId);
            userEquityPropsLog.insert();
            DateTime now = DateTime.now();
            userEquityPropsList.forEach(userEquityProps -> {
                        userEquityProps.setHoldingStatus(UserEquityPropsHoldingStatusEnum.CONSUME);
                        userEquityProps.setUseTime(now);
                        userEquityProps.setUseType(userEquityPropsLog.getUseType());
                    }
            );
            return userEquityPropsDao.updateBatchById(userEquityPropsList);
        }
        return Boolean.FALSE;
    }

    @Override
    public Boolean freezePropsToNormalByIds(String ids, Long userId) {
        //查询出所有的权益道具
        List<UserEquityProps> userEquityPropsList = userEquityPropsDao.getListByUserIdAndIds(userId, ids, UserEquityPropsHoldingStatusEnum.FREEZE);
        if (userEquityPropsList.size() > 0) {
            userEquityPropsList.forEach(userEquityProps -> userEquityProps.setHoldingStatus(UserEquityPropsHoldingStatusEnum.NORMAL));
            return userEquityPropsDao.updateBatchById(userEquityPropsList);
        }
        return Boolean.FALSE;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void subVoucher(Long equityPropsId, EquityPropsTypeEnum equityPropsType, Long userId, int num, String relationTitle, Long relationId) {
        //获取抽奖券
        List<UserEquityProps> userEquityPropsList = userEquityPropsDao.getVoucherList(equityPropsId, userId, equityPropsType, num);
        if (CollUtil.isEmpty(userEquityPropsList) || userEquityPropsList.size() < num) {
            throw new GlobalRunTimeException(ErrorCode.VOUCHER_NOT_ENOUGH);
        }
        doSubVoucher(userEquityPropsList, userId, num, relationTitle, relationId, UserEquityPropsUseTypeEnum.EXCHANGE);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<Long> subVoucher(Long equityPropsId, EquityPropsTypeEnum equityPropsType, Long userId, int num, String relationTitle, Long relationId, UserEquityPropsUseTypeEnum userEquityPropsUseTypeEnum) {
        List<UserEquityProps> userEquityPropsList = userEquityPropsDao.getVoucherList(equityPropsId, userId, equityPropsType, num);
        if (CollUtil.isEmpty(userEquityPropsList) || userEquityPropsList.size() < num) {
            throw new GlobalRunTimeException(ErrorCode.VOUCHER_NOT_ENOUGH);
        }
        doSubVoucher(userEquityPropsList, userId, num, relationTitle, relationId, userEquityPropsUseTypeEnum);
        return userEquityPropsList.stream().map(UserEquityProps::getId).collect(Collectors.toList());
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void subVoucher(Long equityPropsId, Long userId, int num, String relationTitle, Long relationId, EquityPropsTypeEnum... equityPropsType) {
        //获取抽奖券
        List<UserEquityProps> userEquityPropsList = userEquityPropsDao.getVoucherList(equityPropsId, userId, num, equityPropsType);
        if (CollUtil.isEmpty(userEquityPropsList) || userEquityPropsList.size() < num) {
            throw new GlobalRunTimeException(ErrorCode.VOUCHER_NOT_ENOUGH);
        }
        doSubVoucher(userEquityPropsList, userId, num, relationTitle, relationId, UserEquityPropsUseTypeEnum.EXCHANGE);
    }

    private void doSubVoucher(List<UserEquityProps> userEquityPropsList, Long userId, Integer num, String relationTitle, Long relationId, UserEquityPropsUseTypeEnum userEquityPropsUseTypeEnum) {
        DateTime now = DateTime.now();
        userEquityPropsList.forEach(userEquityProps -> {
                    userEquityProps.setHoldingStatus(UserEquityPropsHoldingStatusEnum.CONSUME);
                    userEquityProps.setUseTime(now);
                    userEquityProps.setUseType(userEquityPropsUseTypeEnum);
                }
        );


        userEquityPropsDao.updateBatchById(userEquityPropsList);

        String userEquityPropsIds = userEquityPropsList.stream().map(UserEquityProps::getId).map(String::valueOf).collect(Collectors.joining(","));
        //插入日志
        UserEquityPropsLog userEquityPropsLog = new UserEquityPropsLog();
        userEquityPropsLog.setUserId(userId);
        userEquityPropsLog.setUserEquityPropsId(userEquityPropsIds);
        userEquityPropsLog.setFirstTitle(userEquityPropsList.get(0).getFirstTitle());
//        userEquityPropsLog.setPropsId(userEquityPropsList.get(0).getEquityPropsId());
        userEquityPropsLog.setCreationContent(userEquityPropsList.get(0).getCreationContent());
        userEquityPropsLog.setGetType(null);
        userEquityPropsLog.setUseType(userEquityPropsUseTypeEnum);
        userEquityPropsLog.setTypeClassify(userEquityPropsList.get(0).getTypeClassify());
        userEquityPropsLog.setIsConsume(Boolean.TRUE);
        userEquityPropsLog.setCount(num);
        userEquityPropsLog.setRelationTitle(relationTitle);
        userEquityPropsLog.setRelationId(relationId);
        userEquityPropsLog.insert();
    }

    @Override
    public Long subVoucherIndependent(Long equityPropsId, EquityPropsTypeEnum equityPropsType, Long userId, String relationTitle, Long relationId) {
        //获取抽奖券
        List<UserEquityProps> userEquityPropsList = userEquityPropsDao.getVoucherList(equityPropsId, userId, equityPropsType, 1);
        if (CollUtil.isEmpty(userEquityPropsList) || userEquityPropsList.size() < 1) {
            throw new GlobalRunTimeException(ErrorCode.VOUCHER_NOT_ENOUGH);
        }
        DateTime now = DateTime.now();
        userEquityPropsList.forEach(userEquityProps -> {
                    userEquityProps.setHoldingStatus(UserEquityPropsHoldingStatusEnum.CONSUME);
                    userEquityProps.setUseTime(now);
                    userEquityProps.setUseType(UserEquityPropsUseTypeEnum.EXCHANGE);
                }
        );


        userEquityPropsDao.updateBatchById(userEquityPropsList);

        String userEquityPropsIds = userEquityPropsList.stream().map(UserEquityProps::getId).map(String::valueOf).collect(Collectors.joining(","));
        //插入日志
        UserEquityPropsLog userEquityPropsLog = new UserEquityPropsLog();
        userEquityPropsLog.setUserId(userId);
        userEquityPropsLog.setUserEquityPropsId(userEquityPropsIds);
        userEquityPropsLog.setFirstTitle(userEquityPropsList.get(0).getFirstTitle());
//        userEquityPropsLog.setPropsId(userEquityPropsList.get(0).getEquityPropsId());
        userEquityPropsLog.setCreationContent(userEquityPropsList.get(0).getCreationContent());
        userEquityPropsLog.setGetType(null);
        userEquityPropsLog.setUseType(UserEquityPropsUseTypeEnum.EXCHANGE);
        userEquityPropsLog.setTypeClassify(userEquityPropsList.get(0).getTypeClassify());
        userEquityPropsLog.setIsConsume(Boolean.TRUE);
        userEquityPropsLog.setCount(1);
        userEquityPropsLog.setRelationTitle(relationTitle);
        userEquityPropsLog.setRelationId(relationId);
        userEquityPropsLog.insert();
        return userEquityPropsList.get(0).getId();
    }

    @Override
    public UserEquityProps exchangeEquityPropsByUser(EquityProps equityProps, Long userId, UserEquityPropsGetTypeEnum getType, Integer count, String relationTitle, Long relationId, BigDecimal buyPrice, Long activityId, UserEquityPropsGetTypeEnum primeType, Long primeId) {
        ArrayList<UserEquityProps> lists = Lists.newArrayList();
        for (int i = 0; i < count; i++) {
            //添加权益道具
            UserEquityProps userEquityProps = new UserEquityProps();
            userEquityProps.setUserId(userId);
            userEquityProps.setEquityPropsId(equityProps.getId());
            userEquityProps.setFirstTitle(equityProps.getFirstTitle());
            userEquityProps.setCreationContent(equityProps.getCreationContent());
            //时间偏移
            userEquityProps.setExpiredTime(DateUtil.offsetDay(DateTime.now(), equityProps.getExpiredDay()));
            userEquityProps.setUserProductUuid(IdUtil.getSnowflakeNextIdStr());
            userEquityProps.setHoldingStatus(UserEquityPropsHoldingStatusEnum.NORMAL);
            userEquityProps.setGetType(getType);
            userEquityProps.setTypeClassify(equityProps.getTypeClassify());
            userEquityProps.setBuyPrice(buyPrice);
            userEquityProps.setActivityId(activityId);
            userEquityProps.setPrimeType(primeType);
            userEquityProps.setPrimeId(primeId);
            userEquityProps.setUuid(String.valueOf(IdUtil.getSnowflakeNextId()));
            lists.add(userEquityProps);
        }
        //批量插入
        Assert.isTrue(userEquityPropsDao.insertBatchByList(lists), () -> new GlobalRunTimeException(ErrorCode.WRITE_FAILED_PLEASE_TRY_AGAIN_LATER));
        //遍历id
        String userEquityPropsIds = lists.stream().map(UserEquityProps::getId).map(String::valueOf).collect(Collectors.joining(","));

        //记录日志
        UserEquityPropsLog userEquityPropsLog = new UserEquityPropsLog();
        userEquityPropsLog.setUserId(userId);
        userEquityPropsLog.setUserEquityPropsId(userEquityPropsIds);
        userEquityPropsLog.setFirstTitle(equityProps.getFirstTitle());
//        userEquityPropsLog.setPropsId(equityProps.getId());
        userEquityPropsLog.setCreationContent(equityProps.getCreationContent());
        userEquityPropsLog.setGetType(getType);
        userEquityPropsLog.setTypeClassify(equityProps.getTypeClassify());
        userEquityPropsLog.setCount(count);
        userEquityPropsLog.setRelationTitle(relationTitle);
        userEquityPropsLog.setRelationId(relationId);
        userEquityPropsLog.insert();

        return lists.get(0);
    }

    @Override
    public UserEquityProps addEquityPropsByUser(EquityProps equityProps, Long userId, UserEquityPropsGetTypeEnum getType,
                                                Integer count, String relationTitle, Long relationId, BigDecimal buyPrice, UserEquityPropsGetTypeEnum primeType, Long primeId) {
        ArrayList<UserEquityProps> lists = Lists.newArrayList();
        for (int i = 0; i < count; i++) {
            //添加权益道具
            UserEquityProps userEquityProps = new UserEquityProps();
            userEquityProps.setUserId(userId);
            userEquityProps.setEquityPropsId(equityProps.getId());
            userEquityProps.setFirstTitle(equityProps.getFirstTitle());
            userEquityProps.setCreationContent(equityProps.getCreationContent());
            //时间偏移
            userEquityProps.setExpiredTime(DateUtil.offsetDay(DateTime.now(), equityProps.getExpiredDay()));
            userEquityProps.setUserProductUuid(IdUtil.getSnowflakeNextIdStr());
            userEquityProps.setHoldingStatus(UserEquityPropsHoldingStatusEnum.NORMAL);
            userEquityProps.setGetType(getType);
            userEquityProps.setTypeClassify(equityProps.getTypeClassify());
            userEquityProps.setBuyPrice(buyPrice);
            userEquityProps.setPrimeType(primeType);
            userEquityProps.setPrimeId(primeId);
            userEquityProps.setUuid(String.valueOf(IdUtil.getSnowflakeNextId()));
            lists.add(userEquityProps);
        }
        //批量插入
        Assert.isTrue(userEquityPropsDao.insertBatchByList(lists), () -> new GlobalRunTimeException(ErrorCode.WRITE_FAILED_PLEASE_TRY_AGAIN_LATER));
        //遍历id
        List<Long> collect = lists.stream().map(UserEquityProps::getId).collect(Collectors.toList());
        Long minId = collect.stream().min(Long::compareTo).get();
        Long maxId = collect.stream().max(Long::compareTo).get();
        //记录日志
        UserEquityPropsLog userEquityPropsLog = new UserEquityPropsLog();
        userEquityPropsLog.setUserId(userId);
        userEquityPropsLog.setUserEquityPropsId(minId + "->" + maxId);
        userEquityPropsLog.setFirstTitle(equityProps.getFirstTitle());
//        userEquityPropsLog.setPropsId(equityProps.getId());
        userEquityPropsLog.setCreationContent(equityProps.getCreationContent());
        userEquityPropsLog.setGetType(getType);
        userEquityPropsLog.setTypeClassify(equityProps.getTypeClassify());
        userEquityPropsLog.setCount(count);
        userEquityPropsLog.setRelationTitle(relationTitle);
        userEquityPropsLog.setRelationId(relationId);
        userEquityPropsLog.insert();

        return lists.get(0);
    }

    @Override
    public UserEquityProps buyEquityPropsByUser(EquityProps equityProps, Long userId, UserEquityPropsGetTypeEnum getType, List<UserEquityProps> userEquityPropsList, String relationTitle, Long relationId, BigDecimal buyPrice) {

        ArrayList<UserEquityProps> lists = Lists.newArrayList();
        for (UserEquityProps oldUserEquityProps : userEquityPropsList) {
            //添加权益道具
            UserEquityProps userEquityProps = new UserEquityProps();
            userEquityProps.setUserId(userId);
            userEquityProps.setEquityPropsId(equityProps.getId());
            userEquityProps.setFirstTitle(equityProps.getFirstTitle());
            userEquityProps.setCreationContent(equityProps.getCreationContent());
            //时间偏移
            userEquityProps.setExpiredTime(DateUtil.offsetDay(DateTime.now(), equityProps.getExpiredDay()));
            userEquityProps.setUserProductUuid(IdUtil.getSnowflakeNextIdStr());
            userEquityProps.setHoldingStatus(UserEquityPropsHoldingStatusEnum.NORMAL);
            userEquityProps.setGetType(getType);
            userEquityProps.setTypeClassify(equityProps.getTypeClassify());
            userEquityProps.setBuyPrice(buyPrice);
            userEquityProps.setPrimeType(ObjectUtil.isNull(oldUserEquityProps.getPrimeType()) ? getType : oldUserEquityProps.getPrimeType());
            userEquityProps.setPrimeId(relationId);
            userEquityProps.setUuid(oldUserEquityProps.getUuid());
            lists.add(userEquityProps);
        }
        //批量插入
        Assert.isTrue(userEquityPropsDao.insertBatchByList(lists), () -> new GlobalRunTimeException(ErrorCode.WRITE_FAILED_PLEASE_TRY_AGAIN_LATER));
        //遍历id
        String userEquityPropsIds = lists.stream().map(UserEquityProps::getId).map(String::valueOf).collect(Collectors.joining(","));

        //记录日志
        UserEquityPropsLog userEquityPropsLog = new UserEquityPropsLog();
        userEquityPropsLog.setUserId(userId);
        userEquityPropsLog.setUserEquityPropsId(userEquityPropsIds);
        userEquityPropsLog.setFirstTitle(equityProps.getFirstTitle());
//        userEquityPropsLog.setPropsId(equityProps.getId());
        userEquityPropsLog.setCreationContent(equityProps.getCreationContent());
        userEquityPropsLog.setGetType(getType);
        userEquityPropsLog.setTypeClassify(equityProps.getTypeClassify());
        userEquityPropsLog.setCount(userEquityPropsList.size());
        userEquityPropsLog.setRelationTitle(relationTitle);
        userEquityPropsLog.setRelationId(relationId);
        userEquityPropsLog.insert();

        return lists.get(0);
    }

    @Override
    public Page<PageEquityPropsLogVO> getPageEquityPropsLog(UserInfo userInfo, Integer isConsume, Integer pageNo, Integer pageSize) {
        return userEquityPropsLogDao.getPageEquityPropsLog(new Page<>(pageNo, pageSize), isConsume, userInfo.getId());
    }

    @Override
    public Page<PageUserEquityPropsVO> getPageUserEquityProps(UserInfo user, Integer isExpired, Integer pageNo, Integer pageSize) {
        return userEquityPropsDao.getPageUserEquityProps(new Page<>(pageNo, pageSize), user.getId(), isExpired);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean normalToconsumeByIds(List<UserEquityProps> userEquityPropsList, Long userId, String relationTitle, Long relationId, UserEquityPropsUseTypeEnum useType) {
        Date now = DateTime.now();
        userEquityPropsList.forEach(userEquityProps -> {
            userEquityProps.setHoldingStatus(UserEquityPropsHoldingStatusEnum.CONSUME);
            userEquityProps.setUseTime(now);
            userEquityProps.setUseType(useType);
        });
        Boolean falg = userEquityPropsDao.updateBatchById(userEquityPropsList);

        String userEquityPropsIds = userEquityPropsList.stream().map(UserEquityProps::getId).map(String::valueOf).collect(Collectors.joining(","));
        //插入日志
        UserEquityPropsLog userEquityPropsLog = new UserEquityPropsLog();
        userEquityPropsLog.setUserId(userId);
        userEquityPropsLog.setUserEquityPropsId(userEquityPropsIds);
        userEquityPropsLog.setFirstTitle(userEquityPropsList.get(0).getFirstTitle());
//        userEquityPropsLog.setPropsId(userEquityPropsList.get(0).getEquityPropsId());
        userEquityPropsLog.setCreationContent(userEquityPropsList.get(0).getCreationContent());
        userEquityPropsLog.setGetType(null);
        userEquityPropsLog.setUseType(useType);
        userEquityPropsLog.setTypeClassify(userEquityPropsList.get(0).getTypeClassify());
        userEquityPropsLog.setIsConsume(Boolean.TRUE);
        userEquityPropsLog.setCount(userEquityPropsList.size());
        userEquityPropsLog.setRelationTitle(relationTitle);
        userEquityPropsLog.setRelationId(relationId);
        userEquityPropsLog.insert();
        return falg;
    }

    @Override
    public List<IncrementalLossCalculationVO> incrementalLossCalculation(IncrementalLossCalculationDTO incrementalLossCalculationDTO, UserInfo user) {
        List<IncrementalLossCalculationVO> list = new ArrayList<>();
        List<PropGift> byPropId = propGiftDao.getByPropId(incrementalLossCalculationDTO.getPropId());
        if (CollUtil.isNotEmpty(byPropId)) {
            byPropId.forEach(propGift -> {
                // 根据propId,获取所需要的条件.根据不同的条件做不同的返回计算
                IncrementalLossCalculationVO incrementalLossCalculationVO = new IncrementalLossCalculationVO();
                // 获取用户的数据
                Integer consumeType = propGift.getConsumeType();
                if (consumeType.equals(1)) {
                    UserAssets byUserIdAndCoinId = userAssetsDao.getByUserIdAndCoinId(user.getId(), CoinCategoryEnum.INTEGRAL.getCode());
                    incrementalLossCalculationVO.userDebris(byUserIdAndCoinId);
                } else if (consumeType.equals(2)) {
                    UserWallet byUserId = userWalletService.getByUserId(user.getId());
                    incrementalLossCalculationVO.userBalance(byUserId);
                } else {
                    UserEcologyPoints userEcologyPoints = userEcologyPointsService.getOneByUserId(user.getId());
                    incrementalLossCalculationVO.userEcology(userEcologyPoints);
                }
                incrementalLossCalculationVO.calculate(propGift, incrementalLossCalculationDTO.getSum());
                list.add(incrementalLossCalculationVO);
            });
        }
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void gift(GiftCT giftCT) {
        List<UserEquityProps> userIdAndPropIdsAndTypeEnumAndStatusEnum = userEquityPropsDao.getUserIdAndIdsAndTypeEnumAndStatusEnum(giftCT.getUserInfo().getId(), giftCT.getGiftId(), UserEquityPropsHoldingStatusEnum.NORMAL, EquityPropsTypeEnum.VIRTUAL_PROPS, EquityPropsTypeEnum.RAFFLE_TICKET, EquityPropsTypeEnum.VOUCHER);
        if (CollUtil.isEmpty(userIdAndPropIdsAndTypeEnumAndStatusEnum)) {
            throw new GlobalRunTimeException("道具不存在");
        }
        UserChainInfo giftUserChainInfo = userChainInfoDao.getByUserId(giftCT.getUserInfo().getId());
        giftCT.setGiftUserChainInfo(giftUserChainInfo);
        if (!giftCT.selfDenial()) {
            throw new GlobalRunTimeException("赠送人不能是自己");
        }

        EquityProps equityProps = equityPropsDao.getById(userIdAndPropIdsAndTypeEnumAndStatusEnum.get(0).getEquityPropsId());
        if (!equityProps.getIsGift()) {
            throw new GlobalRunTimeException("转赠功能已关闭");
        }

        for (UserEquityProps userEquityProps : userIdAndPropIdsAndTypeEnumAndStatusEnum) {
            userEquityProps.setPrimeType(userEquityProps.getGetType());
            userEquityProps.setPrimeId(userEquityProps.getId());
        }

        giftCT.setUserEquityProps(userIdAndPropIdsAndTypeEnumAndStatusEnum);
        // 根据地址,获取用户
        UserChainInfo registerByUserId = userChainInfoDao.getByAddr(giftCT.getAddress());
        giftCT.setUserChainInfo(registerByUserId);
        // 获取受增用户.
        UserInfo complimentarySubscriber = userInfoDao.getById(registerByUserId.getUserId());
        giftCT.setComplimentarySubscriber(complimentarySubscriber);
        giftCT.setTakeIn(userIdAndPropIdsAndTypeEnumAndStatusEnum);

        if (!giftCT.passwordAuthentification()) {
            throw new GlobalRunTimeException("密码错误");
        }

        // 把转增人的数据,修改为赠送状态
        List<Long> giftIds = userIdAndPropIdsAndTypeEnumAndStatusEnum.stream().map(UserEquityProps::getId).collect(Collectors.toList());
        userEquityPropsDao.gift(giftIds);
        String userEquityPropsIds = giftIds.stream().map(String::valueOf).collect(Collectors.joining(","));
        UserEquityPropsLog delivery = new UserEquityPropsLog();
        delivery.setUserId(giftCT.getUserInfo().getId());
        delivery.setUserEquityPropsId(userEquityPropsIds);
        delivery.setFirstTitle(equityProps.getFirstTitle());
//        delivery.setPropsId(equityProps.getId());
        delivery.setCreationContent(equityProps.getCreationContent());
        delivery.setGetType(UserEquityPropsGetTypeEnum.GIFT);
        delivery.setTypeClassify(equityProps.getTypeClassify());
        delivery.setCount(userIdAndPropIdsAndTypeEnumAndStatusEnum.size());
        delivery.setRelationTitle(StrUtil.format("转赠{}道具卡", giftCT.getComplimentarySubscriber().getNickName()));
        delivery.setRelationId(giftCT.getUserInfo().getId());
        delivery.setIsConsume(Boolean.TRUE);
        delivery.insert();

        // 收货.
        giftCT.takeInGift();
        userEquityPropsDao.saveBatch(giftCT.getTakeIn());
        UserEquityPropsLog userEquityPropsLog = new UserEquityPropsLog();

        userEquityPropsLog.setUserId(giftCT.getComplimentarySubscriber().getId());
        userEquityPropsLog.setUserEquityPropsId(userEquityPropsIds);
        userEquityPropsLog.setFirstTitle(equityProps.getFirstTitle());
//        userEquityPropsLog.setPropsId(equityProps.getId());
        userEquityPropsLog.setCreationContent(equityProps.getCreationContent());
        userEquityPropsLog.setGetType(UserEquityPropsGetTypeEnum.GIFT);
        userEquityPropsLog.setTypeClassify(equityProps.getTypeClassify());
        userEquityPropsLog.setCount(userIdAndPropIdsAndTypeEnumAndStatusEnum.size());
        userEquityPropsLog.setRelationTitle(StrUtil.format("接收{}转赠道具卡", giftCT.getUserInfo().getNickName()));
        userEquityPropsLog.setIsConsume(Boolean.FALSE);
        userEquityPropsLog.setRelationId(giftCT.getUserInfo().getId());
        userEquityPropsLog.insert();

        PropGiftLog propGiftLog = new PropGiftLog();
        // 支付所需的数据
        List<PropGift> byPropId = propGiftDao.getByPropId(equityProps.getId());
        giftCT.calculate(byPropId, userIdAndPropIdsAndTypeEnumAndStatusEnum.size());
        String remark = StrUtil.format("转赠{}铸造券", userIdAndPropIdsAndTypeEnumAndStatusEnum.get(0).getFirstTitle());
        // 记录扣除所需要的钱或者星球碎片消耗 或者生态燃料
        if (giftCT.getConsumeType().equals(1)) {
            propGiftLog.setPaymentSum(giftCT.getDebris());
            userAssetsService.subIntegralByUserId(giftCT.getDebris(), giftCT.getUserInfo().getId(), CoinCategoryEnum.INTEGRAL, AssetChangeLogEnum.GIFT, 0L, "转赠道具卡消耗");
        } else if (giftCT.getConsumeType().equals(2)) {
            UserWallet byUserId = userWalletService.getByUserId(giftCT.getUserInfo().getId());
            if (NumberUtil.isLess(byUserId.getBalance().add(byUserId.getPayBalance()), giftCT.getAmount())) {
                throw new GlobalRunTimeException("余额不足");
            }
            giftCT.setUserWallet(byUserId);
            BigDecimal payBalance = giftCT.getUserWallet().getPayBalance();
            // 扣钱.
            //1.先扣支付余额 2.再扣提现余额
            if (payBalance.compareTo(giftCT.getAmount()) >= 0) { //如果支付账户足够 直接从支付账户扣
                propGiftLog.setPaymentSum(giftCT.getAmount());
                Assert.isTrue(userWalletService.subBalance(giftCT.getUserWallet(), giftCT.getAmount(), 0L, WalletDetailTypeEnum.ITEM_TRANSFER_CREDIT, UserBalanceTypeEnum.PAY_BALANCE, remark), () -> new GlobalRunTimeException(ErrorCode.PAYMENT_FAILED));
            } else {//如果支付账户没钱
                if (payBalance.compareTo(BigDecimal.ZERO) == 0) {//支付账户没钱,直接扣提现账户
                    propGiftLog.setPaymentSum(giftCT.getAmount());
                    Assert.isTrue(userWalletService.subBalance(giftCT.getUserWallet(), giftCT.getAmount(), 0L, WalletDetailTypeEnum.ITEM_TRANSFER, UserBalanceTypeEnum.BALANCE, remark), () -> new GlobalRunTimeException(ErrorCode.PAYMENT_FAILED));
                } else {//如果支付账户有钱 但是不够
                    //先扣除支付账户
                    propGiftLog.setPaymentSum(giftCT.getAmount());
                    Assert.isTrue(userWalletService.subBalance(giftCT.getUserWallet(), payBalance, 0L, WalletDetailTypeEnum.ITEM_TRANSFER_CREDIT, UserBalanceTypeEnum.PAY_BALANCE, remark), () -> new GlobalRunTimeException(ErrorCode.PAYMENT_FAILED));
                    BigDecimal subtract = giftCT.getAmount().subtract(payBalance);
                    Assert.isTrue(userWalletService.subBalance(giftCT.getUserWallet(), subtract, 0L, WalletDetailTypeEnum.ITEM_TRANSFER, UserBalanceTypeEnum.BALANCE, remark), () -> new GlobalRunTimeException(ErrorCode.PAYMENT_FAILED));
                }
            }
        } else {
            //生态燃料扣除
            UserEcologyPoints userEcologyPoints = userEcologyPointsService.getOneByUserId(giftCT.getUserInfo().getId());
            if (NumberUtil.isGreater(giftCT.getEcology(), userEcologyPoints.getAmount())) {
                throw new GlobalRunTimeException("生态燃料不足");
            }
            propGiftLog.setPaymentSum(giftCT.getEcology());
            Assert.isTrue(userEcologyPointsService.subAmount(giftCT.getUserInfo().getId(), giftCT.getEcology(), EcologyPointsEnum.GIFT_PROPS, StrUtil.format("转赠{}:{}", complimentarySubscriber.getNickName(), equityProps.getFirstTitle())), () -> new GlobalRunTimeException("扣除生态燃料失败"));
        }

        propGiftLog.setPropId(equityProps.getId());
        propGiftLog.setConsumeType(giftCT.getConsumeType());
        propGiftLog.setQuantityConsume(Convert.toStr(userIdAndPropIdsAndTypeEnumAndStatusEnum.size()));
        propGiftLog.setAddress(giftCT.getAddress());
        propGiftLog.setTitle(userIdAndPropIdsAndTypeEnumAndStatusEnum.get(0).getFirstTitle());
        propGiftLog.setGiftUserId(giftCT.getUserInfo().getId());
        propGiftLog.setReceiveUserId(giftCT.getComplimentarySubscriber().getId());
        propGiftLog.setGiftPropIds(userEquityPropsIds);
        propGiftLog.insert();
    }

    @Override
    public AddressUserInfoVO addressUserInfo(AddressUserInfoDTO addressUserInfoDTO, UserInfo user) {
        UserChainInfo userChainInfo = userChainInfoDao.getByAddr(addressUserInfoDTO.getChainUrl());
        if (BeanUtil.isEmpty(userChainInfo)) {
            throw new GlobalRunTimeException("地址不存在");
        }
        UserInfo userInfo = userInfoDao.getById(userChainInfo.getUserId());
        if (BeanUtil.isEmpty(userInfo)) {
            throw new GlobalRunTimeException("用户不存在");
        }
        if (addressUserInfoDTO.getCollectionId() != null) {
            // 如果说这个藏品是分解藏品(充值类)的话,那么就要进行判定,确定他是不是可交易的
            if (digitalCollectionProductInfoDao.getWhetherToBreakDownTheCollection(addressUserInfoDTO.getCollectionId())) {
                StaticData topUpGive = staticDataDao.getByType("top_up_give");
                if (topUpGive.getValue().equals("0")) {
                    throw new GlobalRunTimeException("充值类藏品不可交易");
                }
                if (!userInfo.getIsSm()) {
                    throw new GlobalRunTimeException("目标不是有效用户");
                }
                if (!userRelevanceService.userIdAndRelevanceIdIsIdenticalDictyosome(user.getId(), userInfo.getId())) {
                    throw new GlobalRunTimeException("转赠目标不是您的下级,无法转增");
                }
            }
        }
        AddressUserInfoVO addressUserInfo = BeanUtil.copyProperties(userInfo, AddressUserInfoVO.class);
        DigitalCollection digitalCollection = digitalCollectionDao.getById(addressUserInfoDTO.getCollectionId());
        if (digitalCollection.getIsGive()) {
            EcologyCastGasVO ecologyCastGasVO = new EcologyCastGasVO();
            ecologyCastGasVO.setConsumeCost(digitalCollection.getGasCost());
            addressUserInfo.setEcologyCastGas(ecologyCastGasVO);
        }
        return addressUserInfo;
    }

    @Override
    public Page<AdminUserEquityPropsPagVO> getAdminUserEquityPropsPage(String userTel, String firstTitle, Date getBeginTime, Date getEndTime, Date expiredBeginTime, Date expiredEndTime, Page page, Integer onConsignStatus) {
        return userEquityPropsDao.getAdminUserEquityPropsPage(page, userTel, firstTitle, getBeginTime, getEndTime, expiredBeginTime, expiredEndTime, onConsignStatus);
    }

    @Override
    public void batchEditExpiredTime(List<Long> ids, Date expiredTime) {
        Assert.isTrue(
                userEquityPropsDao.getCountByIdsAndHoldStats(ids, UserEquityPropsHoldingStatusEnum.NORMAL).intValue()
                        == ids.size(),
                () -> new GlobalRunTimeException("数量不匹配"));

        Assert.isTrue(userEquityPropsDao.batchEditExpiredTime(ids, expiredTime), () -> new GlobalRunTimeException("批量修改过期时间失败"));
    }

    @Override
    public Page<UserEquityPropsVO> getMyEquity(Long userId, Integer pageNo, Integer pageSize) {
        StaticData scrollPropsId = staticDataDao.getByType("scroll_props_id");

        Page<UserEquityPropsVO> page = userEquityPropsDao.getMyEquity(userId, ObjectUtil.isNotNull(scrollPropsId) ? Long.parseLong(scrollPropsId.getValue()) : null, pageNo, pageSize);
        String value = staticDataDao.getByType("special_give_props_id").getValue();
        List<Long> secondConfIds = secondEquityPropsConfigService.getIdsByStatus(Boolean.TRUE);
        JSONArray array = JSONArray.parseArray(value);
        for (UserEquityPropsVO record : page.getRecords()) {
            if (!CollectionUtils.isEmpty(secondConfIds) && secondConfIds.size() > 0 && secondConfIds.contains(record.getId())) {
                record.setIsConsign(Boolean.TRUE);
                record.setIsGift(Boolean.FALSE);
            }
            if (array.contains(record.getId())) {
                record.setIsGift(Boolean.FALSE);
            }
        }

        return page;
    }

    @Override
    public Page<UserEquityPropsDetailVO> getMyEquityDetail(Long userId, Long id, Integer isExpired, Page page, Boolean isGift) {
        Page<UserEquityPropsDetailVO> resultPage = userEquityPropsDao.getMyEquityDetail(userId, id, isExpired, page, isGift);

        String value = staticDataDao.getByType("special_give_props_id").getValue();
        List<Long> secondConfIds = secondEquityPropsConfigService.getIdsByStatus(Boolean.TRUE);
        JSONArray array = JSONArray.parseArray(value);
        for (UserEquityPropsDetailVO record : resultPage.getRecords()) {
            if (!CollectionUtils.isEmpty(secondConfIds) && secondConfIds.size() > 0 && secondConfIds.contains(record.getId())) {
                record.setIsConsign(Boolean.TRUE);
                record.setIsGift(Boolean.FALSE);
            }
            if (array.contains(record.getId())) {
                record.setIsGift(Boolean.FALSE);
            }
        }
        return resultPage;
    }

    @Override
    public EquityPropsLastConsignDetailsVO getLastConsignDetails(Long equityPropsId) {
        return equityPropsDao.getLastConsignDetails(equityPropsId);
    }

    @Override
    public Page<UserConsignEquityPropsPageVO> getUserConsignEquityPropsPage(Long equityPropsId, UserInfo user, Page page) {
        Assert.isTrue(secondEquityPropsConfigService.getIsExistByEquityPropsIdAndStatus(equityPropsId, Boolean.TRUE), () -> new GlobalRunTimeException("此凭证暂未开启寄售"));
        return userEquityPropsDao.getUserConsignEquityPropsPage(page, equityPropsId, user.getId());
    }

    @Override
    public RealAmountVO getUserRealPrice(UserInfo user, Long equityPropsId, List<Long> userEquityPropsIds, BigDecimal consignPrice) {
        Assert.isTrue(user.getIsValid(), () -> new GlobalRunTimeException("不满足寄售条件"));

        SecondEquityPropsConfig secondEquityPropsConfig = secondEquityPropsConfigDao.getLastOneByEquityPropsId(equityPropsId);
        Assert.notNull(secondEquityPropsConfig, () -> new GlobalRunTimeException("此道具暂未开放寄售"));

        Integer count = userEquityPropsDao.getSellableCountByUserIdAndEquityPropsIdAndIds(user.getId(), equityPropsId, userEquityPropsIds);
        Assert.isTrue(count.intValue() == userEquityPropsIds.size(), () -> new GlobalRunTimeException("数量不匹配"));

        //比例的到手价
        BigDecimal scaleAmount = consignPrice.multiply(BigDecimal.ONE.subtract(secondEquityPropsConfig.getCharge().movePointLeft(2)));
        //比例的手续费
        BigDecimal consignCharge = consignPrice.subtract(scaleAmount);
        //最小手续费
        BigDecimal minCharge = secondEquityPropsConfig.getMinCharge();

        //手续费
        consignCharge = NumberUtil.isGreaterOrEqual(consignCharge, minCharge) ? consignCharge : minCharge;

        //最终到手价
        BigDecimal realAmount = consignPrice.subtract(consignCharge).multiply(Convert.toBigDecimal(count));
        Assert.isTrue(NumberUtil.isGreater(realAmount, BigDecimal.ZERO), () -> new GlobalRunTimeException("出售金额必须大于手续费金额"));

        RealAmountVO realAmountVO = new RealAmountVO();
        realAmountVO.setRealAmount(realAmount);
        realAmountVO.setEquityPropsId(equityPropsId);
        realAmountVO.setConsignCount(count);
        realAmountVO.setCharge(consignCharge);
        realAmountVO.setSumCharge(consignCharge.multiply(Convert.toBigDecimal(count)));

        return realAmountVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void consignEquityProps(UserInfo user, Long equityPropsId, List<Long> userEquityPropsIds, BigDecimal consignPrice) {
        //校验
        RealAmountVO userRealPrice = getUserRealPrice(user, equityPropsId, userEquityPropsIds, consignPrice);
        DateTime now = DateTime.now();

        List<SecondEquityProps> rushToBuyAnOrder = new ArrayList<>();
        for (Long userEquityPropsId : userEquityPropsIds) {
            SecondEquityProps secondEquityProps = new SecondEquityProps();
            secondEquityProps.setEquityPropsId(equityPropsId);
            secondEquityProps.setUserEquityPropsId(userEquityPropsId);
            secondEquityProps.setUserId(user.getId());
            secondEquityProps.setStatus(ConSignStatus.ON_SALES);
            secondEquityProps.setOnShelfTime(now);
            secondEquityProps.setOffShelfTime(DateUtil.offset(now, DateField.MINUTE, 3));
            secondEquityProps.setCharge(Convert.toBigDecimal(userRealPrice.getCharge()));
            secondEquityProps.setSalesPrice(consignPrice);
            secondEquityProps.insert();

            //修改寄售中
            Assert.isTrue(userEquityPropsDao.updateOnConsignAById(userEquityPropsId, UserEquityConsignStatusEnum.ON_CONSIGN), () -> new GlobalRunTimeException("寄售失败,请稍后重试"));
            rushToBuyAnOrder.add(secondEquityProps);
        }
        // 事务提交后发送mq
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCommit() {
                for (SecondEquityProps secondEquityProps : rushToBuyAnOrder) {
                    messageQueueHelper.sendMessage(MessageTopic.PROPS_FREE_MARKET, secondEquityProps);
                }
            }
        });

    }

    @Override
    public Boolean getIsHoldEquityDetail(Long userId, Long equityPropsId) {
        SecondEquityPropsConfig equityPropsConfig = secondEquityPropsConfigDao.getLastOneByEquityPropsId(equityPropsId);
        Assert.notNull(equityPropsConfig, () -> new GlobalRunTimeException("此道具暂未开放寄售"));

        return userEquityPropsDao.getIsHoldEquityDetail(userId, equityPropsId);
    }

    @Override
    public List<HoldPropDataVO> holdProp(Long userId, String propName) {
        return userEquityPropsDao.holdProp(userId, propName);
    }

    @Override
    public List<HoldPropDataVO> getSingleHoldEquityPropDataByUserIdAndEquityPropId(Long userId, Long id) {
        return userEquityPropsDao.getSingleHoldEquityPropDataByUserIdAndEquityPropId(userId, id);
    }

    @Override
    public Page<HoldPropDataVO> getSingleHoldEquityPropData(Long userId, Integer pageNo, Integer pageSize, Long id) {
        return userEquityPropsDao.getSingleHoldEquityPropData(userId, pageNo, pageSize, id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateToSales(Long equityPropsId, Long userEquityPropsId, Long orderId, Long salesUserId, Long buyUserId, Date payTime) {
        Assert.isTrue(userEquityPropsDao.updateToSales(userEquityPropsId, orderId, salesUserId, buyUserId, payTime), () -> new GlobalRunTimeException("商品状态不正确，请重新下单"));

        EquityProps equityProps = equityPropsDao.getById(equityPropsId);
        UserEquityProps userEquityProps = userEquityPropsDao.getById(userEquityPropsId);

        UserEquityPropsLog userEquityPropsLog = new UserEquityPropsLog();
        userEquityPropsLog.setUserId(salesUserId);
        userEquityPropsLog.setUserEquityPropsId(buyUserId.toString());
        userEquityPropsLog.setFirstTitle(equityProps.getFirstTitle());
//        userEquityPropsLog.setPropsId(equityProps.getId());
        userEquityPropsLog.setCreationContent(equityProps.getCreationContent());
        userEquityPropsLog.setGetType(userEquityProps.getGetType());
        userEquityPropsLog.setUseType(UserEquityPropsUseTypeEnum.SALES);
        userEquityPropsLog.setTypeClassify(userEquityProps.getTypeClassify());
        userEquityPropsLog.setIsConsume(Boolean.TRUE);
        userEquityPropsLog.setCount(1);
        userEquityPropsLog.setRelationTitle(StrUtil.format("{}:{}", UserEquityPropsUseTypeEnum.SALES.getDescription(), equityProps.getFirstTitle()));
        userEquityPropsLog.setRelationId(orderId);
        userEquityPropsLog.insert();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateWantSellToSales(Long equityPropsId, Long userEquityPropsId, Long orderId, Long salesUserId, Long buyUserId, Date payTime) {
        Assert.isTrue(userEquityPropsDao.updateWantSellToSales(userEquityPropsId, orderId, salesUserId, buyUserId, payTime), () -> new GlobalRunTimeException("商品状态不正确，请重新下单"));

        EquityProps equityProps = equityPropsDao.getById(equityPropsId);
        UserEquityProps userEquityProps = userEquityPropsDao.getById(userEquityPropsId);

        UserEquityPropsLog userEquityPropsLog = new UserEquityPropsLog();
        userEquityPropsLog.setUserId(salesUserId);
        userEquityPropsLog.setUserEquityPropsId(buyUserId.toString());
        userEquityPropsLog.setFirstTitle(equityProps.getFirstTitle());
//        userEquityPropsLog.setPropsId(equityProps.getId());
        userEquityPropsLog.setCreationContent(equityProps.getCreationContent());
        userEquityPropsLog.setGetType(userEquityProps.getGetType());
        userEquityPropsLog.setUseType(UserEquityPropsUseTypeEnum.SALES);
        userEquityPropsLog.setTypeClassify(userEquityProps.getTypeClassify());
        userEquityPropsLog.setIsConsume(Boolean.TRUE);
        userEquityPropsLog.setCount(1);
        userEquityPropsLog.setRelationTitle(StrUtil.format("{}:{}", UserEquityPropsUseTypeEnum.SALES.getDescription(), equityProps.getFirstTitle()));
        userEquityPropsLog.setRelationId(orderId);
        userEquityPropsLog.insert();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateWantBuyOrderToSales(Long equityPropsId, Long userEquityPropsId, Long orderId, Long salesUserId, Long buyUserId, Date payTime) {
        Assert.isTrue(userEquityPropsDao.updateWantBuyOrderToSales(userEquityPropsId, orderId, salesUserId, buyUserId, payTime), () -> new GlobalRunTimeException("商品状态不正确，请重新下单"));

        EquityProps equityProps = equityPropsDao.getById(equityPropsId);
        UserEquityProps userEquityProps = userEquityPropsDao.getById(userEquityPropsId);

        UserEquityPropsLog userEquityPropsLog = new UserEquityPropsLog();
        userEquityPropsLog.setUserId(salesUserId);
        userEquityPropsLog.setUserEquityPropsId(buyUserId.toString());
        userEquityPropsLog.setFirstTitle(equityProps.getFirstTitle());
//        userEquityPropsLog.setPropsId(equityProps.getId());
        userEquityPropsLog.setCreationContent(equityProps.getCreationContent());
        userEquityPropsLog.setGetType(userEquityProps.getGetType());
        userEquityPropsLog.setUseType(UserEquityPropsUseTypeEnum.SALES);
        userEquityPropsLog.setTypeClassify(userEquityProps.getTypeClassify());
        userEquityPropsLog.setIsConsume(Boolean.TRUE);
        userEquityPropsLog.setCount(1);
        userEquityPropsLog.setRelationTitle(StrUtil.format("{}:{}", UserEquityPropsUseTypeEnum.SALES.getDescription(), equityProps.getFirstTitle()));
        userEquityPropsLog.setRelationId(orderId);
        userEquityPropsLog.insert();
    }

    @Override
    public List<UserEquityProps> getListByIds(List<Long> ids) {
        return userEquityPropsDao.getListByIds(ids);
    }

    /**
     * 获取用户权益道具和删除的
     *
     * @param userEquityPropsIds
     * @return
     */
    @Override
    public List<UserEquityProps> getListByIdsAndDelete(List<Long> userEquityPropsIds) {
        return userEquityPropsDao.getListByIdsAndDelete(userEquityPropsIds);
    }

    /**
     * 拍卖道具处理
     *
     * @param userEquityPropsIdList 消耗的用户道具id
     * @param relationId
     * @return
     */
    @Override
    public void disposalOfAuctionItems(List<Long> userEquityPropsIdList, Map<Long, Integer> giveMap, Long relationId, Long copyrightAuctionId, Long copyrightAuctionRecordId) {
        // 消耗
        Long userEquityPropId = userEquityPropsIdList.get(0);
        UserEquityProps userEquityPropsInDb = userEquityPropsDao.getById(userEquityPropId);
        EquityProps equityProps = equityPropsDao.getById(userEquityPropsInDb.getEquityPropsId());
        Date now = DateTime.now();
        Assert.isTrue(userEquityPropsDao.updateByIds(userEquityPropsIdList, UserEquityPropsHoldingStatusEnum.AUCTION_CONSUME, now, UserEquityPropsUseTypeEnum.AUCTION_CONSUMPTION), () -> new GlobalRunTimeException("拍卖消耗道具失败"));
        //插入日志
        UserEquityPropsLog userEquityPropsLog = new UserEquityPropsLog();
        userEquityPropsLog.setUserId(userEquityPropsInDb.getUserId());
        userEquityPropsLog.setUserEquityPropsId(userEquityPropsIdList.toString());
        userEquityPropsLog.setFirstTitle(userEquityPropsInDb.getFirstTitle());
//        userEquityPropsLog.setPropsId(userEquityPropsInDb.getEquityPropsId());
        userEquityPropsLog.setCreationContent(userEquityPropsInDb.getCreationContent());
        userEquityPropsLog.setGetType(null);
        userEquityPropsLog.setUseType(UserEquityPropsUseTypeEnum.AUCTION_CONSUMPTION);
        userEquityPropsLog.setTypeClassify(userEquityPropsInDb.getTypeClassify());
        userEquityPropsLog.setIsConsume(Boolean.TRUE);
        userEquityPropsLog.setCount(userEquityPropsIdList.size());
        userEquityPropsLog.setRelationTitle("拍卖消耗");
        userEquityPropsLog.setRelationId(relationId);
        userEquityPropsLog.insert();

        // 拍卖道具分
        for (Long userId : giveMap.keySet()) {
            Integer num = giveMap.get(userId);
            if (num <= 0) {
                continue;
            }
            CopyrightAuctionDividedLog copyrightAuctionDividedLog = new CopyrightAuctionDividedLog();
            copyrightAuctionDividedLog.setIsHandle(Boolean.FALSE);
            if (userId != 0) {
                ArrayList<UserEquityProps> lists = Lists.newArrayList();
                for (int i = 0; i < num; i++) {
                    //添加权益道具
                    UserEquityProps userEquityProps = new UserEquityProps();
                    userEquityProps.setUserId(userId);
                    userEquityProps.setEquityPropsId(userEquityPropsInDb.getEquityPropsId());
                    userEquityProps.setFirstTitle(userEquityPropsInDb.getFirstTitle());
                    userEquityProps.setCreationContent(userEquityPropsInDb.getCreationContent());
                    //时间偏移
                    userEquityProps.setExpiredTime(DateUtil.offsetDay(DateTime.now(), equityProps.getExpiredDay()));
                    userEquityProps.setUserProductUuid(IdUtil.getSnowflakeNextIdStr());
                    userEquityProps.setHoldingStatus(UserEquityPropsHoldingStatusEnum.NORMAL);
                    userEquityProps.setGetType(UserEquityPropsGetTypeEnum.AUCTION_PRIZE);
                    userEquityProps.setTypeClassify(equityProps.getTypeClassify());
                    userEquityProps.setBuyPrice(BigDecimal.ZERO);
                    userEquityProps.setPrimeType(UserEquityPropsGetTypeEnum.AUCTION_PRIZE);
                    userEquityProps.setPrimeId(relationId);
                    userEquityProps.setUuid(String.valueOf(IdUtil.getSnowflakeNextId()));
                    lists.add(userEquityProps);
                }
                //批量插入
                Assert.isTrue(userEquityPropsDao.insertBatchByList(lists), () -> new GlobalRunTimeException(ErrorCode.WRITE_FAILED_PLEASE_TRY_AGAIN_LATER));
                //遍历id
                List<Long> collect = lists.stream().map(UserEquityProps::getId).collect(Collectors.toList());
                Long minId = collect.stream().min(Long::compareTo).get();
                Long maxId = collect.stream().max(Long::compareTo).get();
                //记录日志
                UserEquityPropsLog addUserEquityPropsLog = new UserEquityPropsLog();
                addUserEquityPropsLog.setUserId(userId);
                addUserEquityPropsLog.setUserEquityPropsId(minId + "->" + maxId);
                addUserEquityPropsLog.setFirstTitle(equityProps.getFirstTitle());
//                addUserEquityPropsLog.setPropsId(equityProps.getId());
                addUserEquityPropsLog.setCreationContent(equityProps.getCreationContent());
                addUserEquityPropsLog.setGetType(UserEquityPropsGetTypeEnum.AUCTION_PRIZE);
                addUserEquityPropsLog.setTypeClassify(equityProps.getTypeClassify());
                addUserEquityPropsLog.setCount(num);
                addUserEquityPropsLog.setRelationTitle("拍卖获取");
                addUserEquityPropsLog.setRelationId(relationId);
                addUserEquityPropsLog.insert();
                copyrightAuctionDividedLog.setIsHandle(Boolean.TRUE);
            }
            copyrightAuctionDividedLog.setCopyrightAuctionId(copyrightAuctionId);
            copyrightAuctionDividedLog.setCopyrightAuctionRecordId(copyrightAuctionRecordId);
            copyrightAuctionDividedLog.setUserId(userId);
            copyrightAuctionDividedLog.setNum(num);
            copyrightAuctionDividedLog.insert();
        }
    }

    @Override
    public void disposalOfAuctionItems(Map<Long, Integer> giveMap, EquityProps equityProps) {
        // 拍卖道具分
        for (Long userId : giveMap.keySet()) {
            Integer num = giveMap.get(userId);
            if (userId != 0) {
                ArrayList<UserEquityProps> lists = Lists.newArrayList();
                for (int i = 0; i < num; i++) {
                    //添加权益道具
                    UserEquityProps userEquityProps = new UserEquityProps();
                    userEquityProps.setUserId(userId);
                    userEquityProps.setEquityPropsId(equityProps.getId());
                    userEquityProps.setFirstTitle(equityProps.getFirstTitle());
                    userEquityProps.setCreationContent(equityProps.getCreationContent());
                    //时间偏移
                    userEquityProps.setExpiredTime(DateUtil.offsetDay(DateTime.now(), equityProps.getExpiredDay()));
                    userEquityProps.setUserProductUuid(IdUtil.getSnowflakeNextIdStr());
                    userEquityProps.setHoldingStatus(UserEquityPropsHoldingStatusEnum.NORMAL);
                    userEquityProps.setGetType(UserEquityPropsGetTypeEnum.AUCTION_PRIZE);
                    userEquityProps.setTypeClassify(equityProps.getTypeClassify());
                    userEquityProps.setBuyPrice(BigDecimal.ZERO);
                    userEquityProps.setPrimeType(UserEquityPropsGetTypeEnum.AUCTION_PRIZE);
                    userEquityProps.setPrimeId(0L);
                    userEquityProps.setUuid(String.valueOf(IdUtil.getSnowflakeNextId()));
                    lists.add(userEquityProps);
                }
                //批量插入
                Assert.isTrue(userEquityPropsDao.insertBatchByList(lists), () -> new GlobalRunTimeException(ErrorCode.WRITE_FAILED_PLEASE_TRY_AGAIN_LATER));
                //遍历id
                List<Long> collect = lists.stream().map(UserEquityProps::getId).collect(Collectors.toList());
                Long minId = collect.stream().min(Long::compareTo).get();
                Long maxId = collect.stream().max(Long::compareTo).get();
                //记录日志
                UserEquityPropsLog addUserEquityPropsLog = new UserEquityPropsLog();
                addUserEquityPropsLog.setUserId(userId);
                addUserEquityPropsLog.setUserEquityPropsId(minId + "->" + maxId);
                addUserEquityPropsLog.setFirstTitle(equityProps.getFirstTitle());
//                addUserEquityPropsLog.setPropsId(equityProps.getId());
                addUserEquityPropsLog.setCreationContent(equityProps.getCreationContent());
                addUserEquityPropsLog.setGetType(UserEquityPropsGetTypeEnum.AUCTION_PRIZE);
                addUserEquityPropsLog.setTypeClassify(equityProps.getTypeClassify());
                addUserEquityPropsLog.setCount(num);
                addUserEquityPropsLog.setRelationTitle("拍卖获取");
                addUserEquityPropsLog.setRelationId(0L);
                addUserEquityPropsLog.insert();
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void mallIssuePropEquity(MallIssuePropEquityDTO mallIssuePropEquityDTO) {
        // 循环进行发放.验证对应的绑定标记是否是对应的道具 如果不是的话则不发放全部回滚报错
        String vistIn = mallIssuePropEquityDTO.getVistIn();
        PropEquityVestIn propEquityVestIn = propEquityVestInDao.getFlag(vistIn);
        for (MallIssuePropEquityListDTO mallIssuePropEquityListDTO : mallIssuePropEquityDTO.getMallIssuePropEquityList()) {
            // 根据道具id获取道具
            EquityProps equityProps = equityPropsDao.getById(mallIssuePropEquityListDTO.getPropId());
            if (!equityProps.getVistIn().equals(propEquityVestIn.getId())) {
                throw new GlobalRunTimeException("道具不匹配");
            }
            // 道具匹配,开始发放
            addEquityPropsByUser(equityProps, mallIssuePropEquityDTO.getUserId(), UserEquityPropsGetTypeEnum.MALL_PRIZE, mallIssuePropEquityListDTO.getCount(), "商城下发", 0L, BigDecimal.ZERO, UserEquityPropsGetTypeEnum.MALL_PRIZE, propEquityVestIn.getId());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void mallSubtractPropEquity(MallDeductPropEquityDTO mallDeductPropEquityDTO) {
        PropEquityVestIn propEquityVestIn = propEquityVestInDao.getFlag(mallDeductPropEquityDTO.getVistIn());
        // 根据道具id获取道具
        for (MallIssuePropEquityListDTO mpp : mallDeductPropEquityDTO.getMallIssuePropEquityList()) {
            EquityProps equityProps = equityPropsDao.getById(mpp.getPropId());
            if (!equityProps.getVistIn().equals(propEquityVestIn.getId())) {
                throw new GlobalRunTimeException("道具不匹配");
            }
            subVoucher(mpp.getPropId(), EquityPropsTypeEnum.VIRTUAL_PROPS, mallDeductPropEquityDTO.getUserId(), mpp.getCount(), "商城扣除", propEquityVestIn.getId(), UserEquityPropsUseTypeEnum.MALL_BUY);
        }
    }

    @Override
    public List<UserHoldPropsCountVO> getUserPropsHoldCount(Long userId, List<Long> equityPropsIds) {
        return userEquityPropsDao.getUserPropsHoldCount(userId, equityPropsIds);
    }
}
